/* Program entrance.
 * This file is part of AGet. See main.h to get more info.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>

#include "main.h"
#include "longopt.h"
#include "aget.h"


/* output: */
#define DESC_STR "AGet, A more program-friendly network retriever.\n"
#define USAGE_STR "Usage: %s [OPTION]... URL\n\n"
#define REPORT_TO "\nOutput field description:\n"\
    "  Line 1: N\n  Line 2: DOWN PERC\n  Desc:\n"\
    "    N is total size(byte) of current download file.\n"\
    "    DOWN is donwloaded size(byte).\n"\
    "    PERC is downloaded percentage.\n"\
    "\nBug reports and suggestions via http://code.google.com/p/aget/\n"


/* application name */
const char* appname;

extern int errno;


/* program entrance: */
int main(int argc, char* argv[], char* envp[])
{
    /* get app name */
    appname = strrchr(argv[0], '/');
    if (appname==NULL)
        appname = argv[0];
    else
        appname++;

    /* init and open socket: */
    int sck = init();

    /* init http */
    httpopt_t hopt = { 0 }; /* init */
    HTTP* http = http_open(sck);
        
    static option_t opts[] = {
        {'-', 0, 0, 0, "Common options:"},
        {'v', "version", LONGOPT_NOPARAM, NULL, "display the version of xget and exit."},
        {'h', "help",    LONGOPT_NOPARAM, NULL, "print this help."},
        {'d', NULL,      LONGOPT_NOPARAM, NULL, "print human-readable debugging info."},
        {'-', "-", 0, 0, "Basic options:"},

        {'p', "port",    LONGOPT_REQUIRE, "PORT", "set port value to PORT."},
        {'r', "retry",   LONGOPT_REQUIRE, "TIMES", "set retry-count to TIMES, =0 means no limit."},
        {'t', "timeout", LONGOPT_REQUIRE, "SECONDS", "set timeout value to SECONDS, =0 means no limit."},
        {'o', "output",  LONGOPT_REQUIRE, "FILE", "set output file pathname to FILE."},
        {'c', "continue",LONGOPT_OPTIONAL,"OFFSET", "resume getting a partially-downloaded file begin with OFFSET."},

        {'-', "-", 0, 0, "HTTP options:"},
        { 0,  "with-header", LONGOPT_OPTIONAL, "FILE", "output HTTP respones header to FILE."},
        { 0,  "save-cookies", LONGOPT_REQUIRE, "FILE", "save cookies into FILE."},
        { 0,  "add-cookie", LONGOPT_REQUIRE, "NAME=VALUE", "add cookie NAME=VALUE to request header."},
        { 0,  "with-request", LONGOPT_NOPARAM, NULL, "output HTTP request."},
        {0, 0, 0, 0, 0}
    };

    int uricnt = 0;
    int opt;
    int i;
    char headerfile[512] = "";
    char filename[512] = "-";
    while ((opt=longopt(argc, argv, opts))!=LONGOPT_DONE) {

        switch (opt) {
            
        case 1: /* -v or --version */
            printf("Version: 0.1\n");
            exit(EXIT_SUCCESS);

        case 2: /* -h or --help */
            goto USAGE_LABEL;
            
        case 3: /* -d */
            AGET_DEBUG = 1;
            break;

        case 5: /* -p or --port */
            intopt(&i, optparam);
            agetopt.port = i>0 ? i : 80;
            break;

        case 6: /* -r/--retry */
            intopt(&i, optparam);
            agetopt.retry = i>0 ? i : INT_MAX;
            break;
            
        case 7: /* -t/--timeout */
            intopt(&i, optparam);
            agetopt.timeout = i>0 ? i : INT_MAX;
            break;

        case 8: /* -o/--output */
            strncpy(filename, optparam, 511);
            break;

        case 9: /* -c/--continue */
            intopt(&i, optparam);
            agetopt.offset = i<0 ? 0 : i;
            break;

        case 11: /* --with-header */
            if (optparam)
                strncpy(headerfile, optparam, 511);
            else
                strcpy(headerfile, "*");
            break;

        case 12: /* --save-cookies */
            if ((agetopt.savecookie=openfile(optparam))==NULL) {
                fprintf(stderr, "Error: can't open file %s for write.\n",
                        optparam);
                exit(EXIT_FAILURE);
            }
            break;

        case 13: /* add-cookie */
            
            break;

        case 14: /* with-request */
            hopt.request = stdout;
            break;

        case LONGOPT_NEED_PARAM:
            fprintf(stderr, "Error: option '%s' require argument.\n",
                    optparam);
            exit(EXIT_FAILURE);

        case LONGOPT_ARG: /* non-option argument */
            if (uricnt==0)
                stringopt(&agetopt.uri, optparam);
            ++uricnt;
            break;
            
        case LONGOPT_UNKNOWN_OPT:
            fprintf(stderr, "Error: unrecognized option '%s'.\n", optparam);
            exit(EXIT_FAILURE);

        default:
            fprintf(stderr, "Option '-%c/--%s' not use yet.\n",
                    opts[opt].val?opts[opt].val:' ',
                    opts[opt].name?opts[opt].name:" ");
        } /* end of switch */
    }
    if (uricnt==0) goto USAGE_LABEL;

    if (filename[0]!='-' || filename[1]!='\0') { /* open file to output */
        if (agetopt.offset>=0) {
            if ((agetopt.fp=openfile(filename))==NULL) {
                fprintf(stderr, "Error: can't open file %s for writing.\n",
                        filename);
                exit(EXIT_FAILURE);                
            }
            if (agetopt.offset>0)
                fseek(agetopt.fp, agetopt.offset, SEEK_SET);
            else
                agetopt.offset = ftell(agetopt.fp);
        }
        else if ((agetopt.fp=fopen(filename, "w"))==NULL) {
            fprintf(stderr, "Error: can't open file %s for writing.\n",
                    filename);
            exit(EXIT_FAILURE);
        }
        else
            agetopt.offset = 0;
    }
    
    if (strlen(headerfile)>0) { /* open header output file */
        if ((agetopt.fh=openfile(headerfile))==NULL) {
            fprintf(stderr, "Error: can't open file %s for writing.\n",
                    headerfile);
            exit(EXIT_FAILURE);
        }
    }

    agetopt.prot = parse_uri(agetopt.uri,
                             &agetopt.host,
                             &agetopt.port,
                             &agetopt.path);
    if (agetopt.prot==0) agetopt.prot = AGET_HTTP;
    dprintf("HOST: %s\nPORT: %u\nPATH: %s\n",
            agetopt.host, agetopt.port, agetopt.path);

    /* retrieve data from remote host: */
    int result = aget(http, &hopt);
    if (result==-1)
        fprintf(stderr, "%s: error occurs on invoking 'gethostbyname'.\n",
                appname);
    else if (result<0)
        perror(appname);

    /* done. cleanup */
    http_close(http);
    cleanup();
    return errno;

USAGE_LABEL: /* to print usage and help info */
    printf(DESC_STR);
    printf(USAGE_STR, appname);
    print_opt(opts);
    printf(REPORT_TO);
    exit(EXIT_SUCCESS);
}

